package jdk6.stax;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.events.XMLEvent;

/**
 * Description: jdk1.6新特性：StAX（StAX）
 * StAX(JSR 173)是JDK6.0中除了DOM和SAX之外的又一种处理XML文档的API
 * StAX 的来历 ：在JAXP1.3(JSR 206)有两种处理XML文档的方法:DOM(Document Object Model)和SAX(Simple API for XML). 
 * 由 于JDK6.0中的JAXB2(JSR 222)和JAX-WS 2.0(JSR 224)都会用到StAX所以Sun决定把StAX加入到JAXP家族当中来，
 * 并将JAXP的版本升级到1.4(JAXP1.4是JAXP1.3的维护版 本). JDK6里面JAXP的版本就是1.4.
 * StAX是The Streaming API for XML的缩写，一种利用拉模式解析(pull-parsing)XML文档的API.
 * StAX通过提供一种基于事件迭代器(Iterator)的API让 程序员去控制xml文档解析过程,程序遍历这个事件迭代器去处理每一个解析事件，
 * 解析事件可以看做是程序拉出来的，也就是程序促使解析器产生一个解析事件 然后处理该事件，之后又促使解析器产生下一个解析事件，如此循环直到碰到文档结束符； 
 * SAX也是基于事件处理xml文档，但却 是用推模式解析，解析器解析完整个xml文档后，才产生解析事件，然后推给程序去处理这些事件；
 * DOM 采用的方式是将整个xml文档映射到一颗内存树，这样就可以很容易地得到父节点和子结点以及兄弟节点的数据，但如果文档很大，将会严重影响性能
 * 
 * XML Parser API Feature Summary Feature         StAX          SAX               DOM                 TrAX    
 * API Type                                       Pull,  streaming Push, streaming In memory tree,  XSLT Rule    
 * Ease of Use                                    High         Medium             High                Medium    
 * XPath Capability                                No            No               Yes                  Yes    
 * CPU and Memory Efficiency                      Good          Good             Varies               Varies    
 * Forward Only                                    Yes           Yes              No                   No    
 * Read XML                                        Yes           Yes              Yes                  Yes    
 * Write XML                                       Yes           No               Yes                  Yes    
 * Create, Read, Update, Delete                    No            No               Yes                  No
 * 
 * 个人认为：一般有用，很多api供开发者挑选了，读取XML文档时出现很多问题，例如读取属性值时读取不出、读取时莫名有些空格以及换行
 * @author Kwum
 * @date 2017年6月17日 上午11:34:24
 * @version 1.0
 */

public class Run {

    public static void main(String[] args) throws FileNotFoundException, XMLStreamException {

        //利用StAX编写XML文档
//        writeXMLByStAX();
        //利用StAX读取XML文档
        readXMLByStAX();
    }
    
    /**
     * 利用StAX编写XML文档
     * @throws FileNotFoundException
     * @throws XMLStreamException
     * @author kwum
     */
    public static void writeXMLByStAX() throws FileNotFoundException, XMLStreamException{
        XMLOutputFactory xmlof = XMLOutputFactory.newInstance();
        //创建xml输出流
        XMLStreamWriter xmlWriter = xmlof.createXMLStreamWriter(new FileOutputStream("src/jdk6/stax/dog.xml"));
        //写入默认的xml声明到xml文档
        xmlWriter.writeStartDocument();
        //换行
        xmlWriter.writeCharacters("\n");
        //根目录
        xmlWriter.writeStartElement("dog");
        //属性
        xmlWriter.writeAttribute("name", "Tony");
        //子元素
        xmlWriter.writeStartElement("color");
        xmlWriter.writeCharacters("Yellow");
        xmlWriter.writeEndElement();
        xmlWriter.writeEndElement();
        xmlWriter.writeEndDocument();
        xmlWriter.close();
    }
    
    /**
     * 利用StAX读取XML文档
     * @throws FileNotFoundException
     * @throws XMLStreamException
     * @author kwum
     */
    public static void readXMLByStAX() throws FileNotFoundException, XMLStreamException{
        XMLInputFactory xmlif = XMLInputFactory.newInstance();
        //创建xml输入流
        XMLEventReader xmlEventReader = xmlif.createXMLEventReader(new FileInputStream("src/jdk6/stax/dog.xml"));
        XMLEvent event;
        while(xmlEventReader.hasNext()){
            event = xmlEventReader.nextEvent();
            if(event.isStartElement()){
                System.out.println(event.asStartElement().getName());
            }else if(event.isCharacters()){
                System.out.println(event.asCharacters().getData());
            }else{
                
            }
        }
    }
}
